package com.anti.jdbc.core.executor;

import com.anti.commom.core.exception.DatabaseException;
import com.anti.jdbc.core.executor.meta.FieldElement;
import com.anti.jdbc.core.executor.meta.IdGenerators;
import com.anti.jdbc.core.executor.meta.id.SnowFlakeId;
import com.anti.jdbc.core.executor.supporrt.JdbcBuilder;
import com.anti.jdbc.core.executor.supporrt.Jdbcs;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobHandler;
import org.springframework.util.Assert;

import java.util.UUID;

/**
 * @Description TODO
 * @Author anTi
 * @Date 2021-3-13
 */
public abstract class AbstractExecutor<T> implements Executor<T>  {
    protected static final LobHandler LOBHANDLER = new DefaultLobHandler();

    protected final JdbcBuilder jdbcBuilder;

    public  AbstractExecutor(JdbcBuilder jdbcBuilder){
        this.jdbcBuilder = jdbcBuilder;
    }

    @Override
    public T execute() throws DatabaseException {
        prepare();
        return doExecute();
    }

    protected abstract void prepare();

    protected abstract T doExecute() throws DatabaseException;

    protected Object generatedId(Object persistent, FieldElement fieldElement, Object value){
        Object id=null;
        if((null == value||"".equals(value)||value.equals(0)||value.equals(0L)) && fieldElement.isGeneratedValue()){
            if(IdGenerators.UUID.equals(fieldElement.getGenerator())){
                id = UUID.randomUUID().toString().replaceAll("-", "");
                String errorMsg = "entity："+persistent.getClass().getName()+" Primary key："+fieldElement.getName()+" Setting value failed";
                Jdbcs.invokeMethod(persistent, fieldElement.getWriteMethod(), errorMsg, id);
            }else if(IdGenerators.SNOWFLAKEID.equals(fieldElement.getGenerator())){
                SnowFlakeId snowFlake = new SnowFlakeId(2, 3);
                String errorMsg = "entity："+persistent.getClass().getName()+" Primary key："+fieldElement.getName()+" Setting value failed";
                if("java.lang.Integer".equals(fieldElement.getType().getName())){
                    Integer entityId=new Long(snowFlake.nextId()).intValue();
                    id=entityId;
                } else if("int".equals(fieldElement.getType().getName())){
                    int entityId=new Long(snowFlake.nextId()).intValue();
                    id=entityId;
                }
                else if("java.lang.String".equals(fieldElement.getType().getName())){
                    String entityId=new Long(snowFlake.nextId()).toString();
                    id=entityId;
                }else{
                    id=snowFlake.nextId();
                }
                Jdbcs.invokeMethod(persistent, fieldElement.getWriteMethod(), errorMsg, id);
            }

            return id;
        }
        return value;
    }

    protected boolean isEntity(Class<?> persistentClass){
        return null != persistentClass.getAnnotation(javax.persistence.Entity.class);
    }

    protected void checkEntity(Class<?> persistentClass){
        Assert.isTrue(isEntity(persistentClass), persistentClass + " If it is an entity type, use the @Entity annotation for identification");
    }

}
